using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using YooAsset;

public class ResMgr
{
    private static readonly Dictionary<string, Dictionary<string, object>> packageDic =
        new Dictionary<string, Dictionary<string, object>>();


    /// <summary>
    /// 加载普通资源
    /// </summary>
    /// <param name="assetName"></param>
    /// <param name="completedHandle"></param>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    public static T LoadAssetAsync<T>(string packageName, string assetName,
        Action<AssetHandle> completedHandle)
        where T : UnityEngine.Object
    {
        if (TryGetDictionary(packageName).ContainsKey(assetName))
        {
            completedHandle?.Invoke(packageDic[packageName][assetName] as AssetHandle);
            return packageDic[packageName][assetName] as T;
        }

        AssetHandle handle = YooAssets.GetPackage(packageName).LoadAssetAsync<T>(assetName);
        handle.Completed += completedHandle;
        packageDic[packageName].Add(assetName, handle);
        return handle.AssetObject as T;
    }

    /// <summary>
    /// 加载精灵图集
    /// </summary>
    /// <param name="AssetName"></param>
    /// <param name="spriteName"></param>
    /// <param name="completedHandle"></param>
    /// <returns></returns>
    public static Sprite LoadSpriteAsync(string packageName, string assetName, string spriteName,
        Action<SubAssetsHandle> completedHandle)
    {
        if (TryGetDictionary(packageName).ContainsKey(assetName))
        {
            completedHandle?.Invoke(packageDic[packageName][assetName] as SubAssetsHandle);
            var subAssetHandle = packageDic[packageName][assetName] as SubAssetsHandle;
            return subAssetHandle.GetSubAssetObject<Sprite>(spriteName);
        }

        SubAssetsHandle handle = YooAssets.GetPackage(packageName).LoadSubAssetsAsync<Sprite>(assetName);
        handle.Completed += completedHandle;
        packageDic[packageName].Add(assetName, handle);
        return handle.GetSubAssetObject<Sprite>(spriteName);
    }

    /// <summary>
    /// 加载场景
    /// </summary>
    /// <param name="sceneName"></param>
    /// <param name="mode"></param>
    /// <param name="activeOnLoad"></param>
    /// <param name="completedHandle"></param>
    public static SceneHandle LoadSceneAsync(string packageName, string sceneName,
        LoadSceneMode mode = LoadSceneMode.Single, bool activeOnLoad = true)
    {
        SceneHandle handle = null;
        if (TryGetDictionary(packageName).ContainsKey(sceneName))
        {
            handle = packageDic[packageName][sceneName] as SceneHandle;
            SceneManager.LoadSceneAsync(handle.SceneObject.name, mode);
            return handle;
        }

        handle = YooAssets.GetPackage(packageName).LoadSceneAsync(sceneName, mode, activeOnLoad);
        return handle;
    }

    /// <summary>
    /// 加载原生文件封装
    /// </summary>
    /// <param name="assetName"></param>
    /// <param name="completedHandle"></param>
    /// <returns></returns>
    public static RawFileHandle LoadRawFileAsync(string packageName, string assetName,
        Action<RawFileHandle> completedHandle)
    {
        if (TryGetDictionary(packageName).ContainsKey(assetName))
        {
            completedHandle?.Invoke(packageDic[packageName][assetName] as RawFileHandle);
            return packageDic[packageName][assetName] as RawFileHandle;
        }

        RawFileHandle handle = YooAssets.GetPackage(packageName).LoadRawFileAsync(assetName);
        handle.Completed += completedHandle;
        packageDic[packageName].Add(assetName, handle);
        return handle;
    }

    /// <summary>
    /// 释放指定资源
    /// </summary>
    /// <param name="assetName"></param>
    public static void UnReleaseHandle(string packageName, string assetName)
    {
        if (TryGetDictionary(packageName).ContainsKey(assetName))
        {
            var handle = packageDic[packageName][assetName];
            if (handle is AssetHandle)
            {
                ((AssetHandle)handle).Release();
            }
            else if (handle is SceneHandle) ((SceneHandle)handle).UnloadAsync();
            else if (handle is SubAssetsHandle) ((SubAssetsHandle)handle).Release();
            else if (handle is RawFileHandle) ((RawFileHandle)handle).Release();

            packageDic[packageName].Remove(assetName);
        }
    }

    /// <summary>
    /// 释放package内所有资源
    /// </summary>
    public static void UnReleasePackage(string packageName)
    {
        TryGetDictionary(packageName);
        YooAssets.GetPackage(packageName).ForceUnloadAllAssets();
        packageDic[packageName] = null;
    }

    /// <summary>
    /// 释放所有package资源
    /// </summary>
    public static void UnReleaseAllPackage()
    {
        foreach (var packageName in packageDic.Keys)
        {
            UnReleasePackage(packageName);
        }
    }

    private static Dictionary<string, object> TryGetDictionary(string packageName)
    {
        if (string.IsNullOrEmpty(packageName))
            throw new ArgumentNullException();

        if (packageDic.ContainsKey(packageName) == false)
            packageDic.Add(packageName, new Dictionary<string, object>());

        return packageDic[packageName];
    }

    void OnApplicationQuit()
    {
        UnReleaseAllPackage();
    }
}